﻿using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Package;
using Microsoft.Win32;
using SnClient;
using SwidHelperLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;

using SnShared.Models;

namespace CdmConsoleHelper
{
    class Program
    {
        private static Boolean AutoReset = false;

        private static string CMD_LISTPACKAGES = "ListPackages";
        private static string CMD_REMOVEPACKAGE = "RemovePackage";
        private static string CMD_CREATESWIDTAGFILES = "CreateSwidTagFiles";
        private static string CMD_REPORTINSTALLEDPACKAGES = "ReportInstalledPackages";
        private static string CMD_PACKAGEMANAGER = "PackageManager";
        private static string CMD_AUTORESET = "AutoReset";

        static void Usage()
        {
            Console.WriteLine(
                "CdmConsoleHelper: [ {0} | {1} <PackageName> | {2} | {3} | {4} {{ {5} }} ]", 
                CMD_LISTPACKAGES, 
                CMD_REMOVEPACKAGE,
                CMD_CREATESWIDTAGFILES,
                CMD_REPORTINSTALLEDPACKAGES,
                CMD_PACKAGEMANAGER,
                CMD_AUTORESET);
        }

        static void Main(string[] args)
        {
            if (0 == args.Length)
            {
                Usage();
                return;
            }
            if (0 == String.Compare(CMD_LISTPACKAGES, args[0]))
            {
                //
                // Enumerate packages via managed installer helper
                //

                foreach (var productInstallation in ProductInstallation.GetProducts(
                    null, null, Microsoft.Deployment.WindowsInstaller.UserContexts.Machine))
                {
                    if (true == String.IsNullOrEmpty(productInstallation.LocalPackage))
                        continue;

                    Console.WriteLine(productInstallation.AdvertisedProductName);
                    using (var installPackage = new InstallPackage(
                        productInstallation.LocalPackage, DatabaseOpenMode.ReadOnly))
                    {
                        try
                        {
                            foreach (var filePath in installPackage.Files)
                            {
                                Console.WriteLine(" {0}", filePath.Value);
                            }
                        }
                        catch(ArgumentException)
                        {
                            // Seems to be a bug in file enumeration for some 
                            // packages. Move to the next one.
                        }
                    }
                }
            }
            else if (0 == String.Compare(CMD_REMOVEPACKAGE, args[0]))
            {
                // TODO
            }
            else if ( 0 == String.Compare( CMD_CREATESWIDTAGFILES, args[0] ) )
            {
                Program.GenerateSwidTagFiles();
            }
            else if (0 == String.Compare(CMD_PACKAGEMANAGER, args[0]))
            {

                if (args.Count() > 1 && (0 == String.Compare(CMD_AUTORESET, args[1])))
                {
                    AutoReset = true;
                }
                
                Program.RunPackageManager();
 

            }
            else if ( 0 == String.Compare( CMD_REPORTINSTALLEDPACKAGES, args[0] ) )
            {
                Program.ReportInstalledPackages();
            }
            else 
            {
                Usage();
                return;
            }
        }

        private static void GenerateSwidTagFiles()
        {
            //
            // Enumerate packages via managed installer helper
            //

            foreach ( var productInstallation in ProductInstallation.GetProducts(
                null, null, Microsoft.Deployment.WindowsInstaller.UserContexts.Machine ) )
            {
                if ( true == String.IsNullOrEmpty( productInstallation.LocalPackage ) )
                    continue;

                Console.WriteLine( productInstallation.AdvertisedProductName );
                using ( var installPackage = new InstallPackage(
                    productInstallation.LocalPackage, DatabaseOpenMode.ReadOnly ) )
                {
                    try
                    {
                        List<string> installPackageFiles = new List<string>();
                        foreach ( var filePath in installPackage.Files )
                        {
                            installPackageFiles.Add( filePath.Value.ToString() );
                        }

                        SwidHelper.CreateSwidTagFileForProduct(
                            null,
                            productInstallation.ProductCode,
                            productInstallation.AdvertisedProductName,
                            productInstallation.ProductVersion,
                            productInstallation.Publisher,
                            installPackageFiles );
                    }
                    catch ( ArgumentException )
                    {
                        // Seems to be a bug in file enumeration for some 
                        // packages. Move to the next one.
                    }
                }
            }
        }

        private static void ReportInstalledPackages()
        {
            try
            {
                CDMRestApi report = new CDMRestApi();
                report.Logger = new ConsoleLogging();
                InstalledPackagesHelper.GetInstalledFiles(report);

                
                RemovePackage rp = new RemovePackage();
                rp.ComputerName = Environment.MachineName;

                SoftwarePackage sp = new SoftwarePackage();
                sp.UniqueId = "{4A03706F-666A-4037-7777-5F2748764D10}";
                rp.Package = sp;
                report.RemovePackage(rp);

            }
            catch ( Exception e )
            {
                Console.WriteLine( "Exception: {0}", e.Message );
            }
        }


        //
        // demo code
        //
        const string PackageGuid = "1234";

        private static void RunPackageManager()
        {
            try 
            {
                PackageManager packageManager = new PackageManager();
                packageManager.OnNotifyPackageRemoval += packageManager_OnNotifyPackageRemoval;
                packageManager.Init();
                packageManager.AutoReset = AutoReset;

                Console.WriteLine("Hit q to quit.");                
                while (Console.Read() != 0x71);

                packageManager.Shutdown();
            
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
            }
        }

        static void packageManager_OnNotifyPackageRemoval(string ppwszMessage)
        {
            Console.WriteLine(ppwszMessage);
        }
    }
}
